package yxy.game.pm2.command.infinite;

import org.joda.time.DateTime;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.infinite;
import yxy.cherry.game.base.message.MessageEmitterHandler;
import yxy.cherry.game.base.message.annotation.MessageSource;
import yxy.cherry.game.base.message.annotation.MessageType;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.module.RedisLock;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.command.Command;
import yxy.game.pm2.message.InfiniteMessage;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.battle.BattleHandle;
import yxy.game.pm2.module.battle.BattleModule;
import yxy.game.pm2.module.infinite.InfiniteHandle;
import yxy.game.pm2.module.infinite.InfiniteHandle.BattleState;
import yxy.game.pm2.module.infinite.InfiniteHandle.InfiniteEntry;
import yxy.game.pm2.module.infinite.InfiniteModule;
import yxy.game.pm2.module.infinite.RankInfinite;

import java.util.ArrayList;
import java.util.Collection;

/** 神将试炼 神将试炼主界面 */
@MessageType(proto = Command.InfiniteUI, classtype = InfiniteMessage.InfiniteUIRequest.class)
public class CMD_InfiniteUI extends Command<InfiniteMessage.InfiniteUIRequest> {

	@Override
	public void execute(MessageSource messageSource, InfiniteMessage.InfiniteUIRequest request) {
		String playerCode = messageSource.getTag();

		InfiniteMessage.InfiniteUIResponse.Builder response = InfiniteMessage.InfiniteUIResponse.newBuilder();

		RedisLock lock = InfiniteModule.lock(playerCode);
		try {
			if (lock.tryLock()) {

				InfiniteModule infiniteModule = InfiniteModule.get(playerCode);
				if (infiniteModule == null) {
					send(messageSource, response, Result.ModuleNotOpen);// 模块没开启
					return;
				}

				if (infiniteModule.isBattling()) {
					DateTime now = DateTime.now();
					InfiniteEntry infiniteEntry = new InfiniteEntry(infiniteModule);
					InfiniteHandle.BattleState state = handleBattle(playerCode, infiniteEntry, 1, now);
					infiniteModule = infiniteEntry.resetModule(infiniteModule);
					infiniteModule.set();

					switch (state) {
					case 局中战斗: {
						ArrayList<InfiniteMessage.InfiniteBattle> resps = new ArrayList<>();
						BattleHandle battleHandle = new BattleHandle();
						CurrencyHandle currencyHandle = new CurrencyHandle();
						// 推送当前的战斗
						for (BattleModule battleModule : infiniteEntry.getBattleModules()) {
							if (now.isBefore(battleModule.timeline().getEndTime())) {
								InfiniteMessage.InfiniteBattle.Builder builder = InfiniteMessage.InfiniteBattle.newBuilder();
								builder.setPlayback(battleHandle.playback(battleModule));
								builder.addAllRewards(currencyHandle.packItems(battleModule.getSettlement().reward()));
								resps.add(builder.build());
							}
						}
						sendChanllengeBattling(messageSource, infiniteModule, resps);
					}
						return;
					case 局间三消: {
						sendChanllenge(messageSource, infiniteModule);
					}
						return;
					case 战斗结算: {
						BattleModule battleModule = infiniteEntry.getSettleBattle();
						battleModule.getSettlement().settle();
						infiniteModule = InfiniteModule.get(playerCode);  //数据同步到redis
						sendChanllengeBattleClear(messageSource, battleModule);
					}
						break;
					default:
						break;
					}

				}

				response.setBest(infiniteModule.getBest());
				response.setStart(infiniteModule.startStage());
				response.setToday(infiniteModule.getToday());

				response.addAllBox(infiniteModule.rewardBox());

				Iterable<? extends Integer> boxes = infiniteModule.rewardBox();
				int nextBox = infiniteModule.getBest() % 5 == 0 ? infiniteModule.getBest() + 5 : infiniteModule.getBest() - (infiniteModule.getBest() % 5) + 5;
				if (!boxes.iterator().hasNext()){  //宝箱都领取完
					if (infiniteModule.getBest() == 0){
						response.setStage(5);
					}else if (nextBox >= infiniteModule.getBest()){
						response.setStage(nextBox - infiniteModule.getStart() + 1);
					}else if (nextBox < infiniteModule.getBest()){
						response.setStage(0);
					}
				}
				for (Integer box : boxes) {  // 宝箱未领取完
					if (box > infiniteModule.getBest()){
						response.setStage(box - infiniteModule.startStage() + 1);  //剩余关卡数
						break;
					}else if (box < infiniteModule.getBest()){
						response.setStage(0); //可领取
						break;
					}
				}


				RankInfinite rankInfinite = RankInfinite.getRank(playerCode);
				Collection<RankEntry> top = rankInfinite.top(3);
				int rank = 0;
				for (RankEntry entry : top) {
					String pCode = entry.getKey();
					int best = entry.getValue().intValue();
					PlayerBean playerBean = PlayerBean.get(pCode);

					InfiniteMessage.TopInfinite.Builder builder = InfiniteMessage.TopInfinite.newBuilder();
					builder.setRank(++rank);
					builder.setBest(best);
					builder.setName(playerBean.getName());
					response.addTop(builder);
				}

				{
					int playerRank = rankInfinite.rank(playerCode);
					response.setRank(playerRank);
				}

				send(messageSource, response, Result.Success);
			}
		} catch (Exception e) {
			e.printStackTrace();
			send(messageSource, response, Result.DataError);
		} finally {
			lock.unlock();
		}

	}

	private void send(MessageSource messageSource, InfiniteMessage.InfiniteUIResponse.Builder response, Result result) {
		response.setResult(result.packResult());
		MessageEmitterHandler.getInstance().send(messageSource, response.build());
	}

	private void sendChanllenge(MessageSource messageSource, InfiniteModule infiniteModule) throws Exception {
		String playerCode = messageSource.getTag();
		int stage = infiniteModule.getCurrent() + 1;
		infiniteModule.best(infiniteModule.getCurrent());
		infiniteModule.set();

		InfiniteMessage.InfiniteChanllengeResponse.Builder response = InfiniteMessage.InfiniteChanllengeResponse.newBuilder();
		response.setBattle(new InfiniteHandle().battleResponse(playerCode, stage));
		response.setResult(Result.Success.packResult());
		MessageEmitterHandler.getInstance().send(messageSource, response.build());
	}

	private void sendChanllengeBattling(MessageSource messageSource, InfiniteModule infiniteModule, ArrayList<InfiniteMessage.InfiniteBattle> resps) {
		InfiniteMessage.InfiniteChanllengeExecuteResponse.Builder response = InfiniteMessage.InfiniteChanllengeExecuteResponse.newBuilder();
		response.addAllBattleResp(resps);
		response.setBest(infiniteModule.getBest());
		response.addAllBox(infiniteModule.rewardBox());
		response.setResult(Result.Success.packResult());
		MessageEmitterHandler.getInstance().send(messageSource, response.build());
	}

	private void sendChanllengeBattleClear(MessageSource messageSource, BattleModule battleModule) {
		InfiniteMessage.InfiniteChanllengeBattleClearResponse.Builder response = InfiniteMessage.InfiniteChanllengeBattleClearResponse.newBuilder();
		response.setInfo(new BattleHandle().battleClear(battleModule));
		response.addAllRewards(new CurrencyHandle().packItems(Currency.merge(battleModule.getSettlement().reward())));
		response.setResult(Result.Success.packResult());
		MessageEmitterHandler.getInstance().send(messageSource, response.build());
	}

	private InfiniteHandle.BattleState handleBattle(String playerCode, InfiniteEntry infiniteEntry, int round, DateTime now) {
		if (!infiniteEntry.isBattling()) {
			return BattleState.没有在战斗;
		}
		if (infiniteEntry.getBattleModules().size() <= 0) {
			infiniteEntry.setBattling(false);
			return BattleState.没有在战斗;
		}
		BattleModule battleModule = infiniteEntry.getLastBattle();
		if (battleModule == null) {
			infiniteEntry.setBattling(false);
			return BattleState.没有在战斗;
		}
		DateTime lastBattleEndTime = battleModule.timeline().getEndTime();
		if (lastBattleEndTime != null && now.isBefore(lastBattleEndTime)) {
			System.err.println(now);
			System.err.println(lastBattleEndTime);
			return BattleState.局中战斗;
		}

		if (!battleModule.getBattleResult().equals(BattleResult.LEFT_WIN)) {
			// 输了结算
			infiniteEntry.setSettleBattle(battleModule);
			return BattleState.战斗结算;
		}

		DateTime startTime = lastBattleEndTime.plusMinutes(InfiniteHandle.minuteRestPeriod());
		if (infiniteEntry.getTickTime().isAfter(lastBattleEndTime)) {
			startTime = infiniteEntry.getTickTime().plusMinutes(InfiniteHandle.minuteRestPeriod());
		}
		if (now.isBefore(startTime)) {
			int stage = infiniteEntry.getStage() + 1;
			infinite data = DataCenter.getData(stage, infinite.class);
			if (data == null) {
				// 已经完成最后一关
				infiniteEntry.setSettleBattle(battleModule);
				return BattleState.战斗结算;
			}

			// 三消
			return BattleState.局间三消;
		}
//		if (round >= 2) {
//			infiniteEntry.setSettleBattle(battleModule);
//			return BattleState.战斗结算;
//		}
		infiniteEntry.getBattleModules().clear();
//		new InfiniteHandle().battle(playerCode, null, startTime, infiniteEntry);
//		return handleBattle(playerCode, infiniteEntry, round + 1, now);
		infiniteEntry.setSettleBattle(battleModule);
		return BattleState.战斗结算;
//		//todo 2022.09.20 不再递归循环计算战斗
//		infiniteEntry.setSettleBattle(battleModule);
//		return BattleState.战斗结算;
	}
}